package com.ray.template;

import com.alibaba.fastjson.JSON;
import com.ray.util.StringUtil;
import com.ray.woodencreate.beans.BeanCreate;
import com.ray.woodencreate.exception.BusinessExceptionFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author bo shen
 * @Description: 模板数据处理类
 * @Class: TemplateFactory
 * @Package com.tf56.bms.template
 * @date 2020/2/11 11:05
 * @company <p>Ray快速开发平台</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class TemplateFactory<T> {
    /**
     * 读取模板数据
     *
     * @param entity
     * @return
     */
    public List<TemplateRecord> readTemplate(T entity) {
        List<TemplateRecord> list = new ArrayList<>();
        if (!ObjectUtils.isEmpty(entity)) {
            Class<?> clazz = entity.getClass();
            Template template = clazz.getAnnotation(Template.class);
            if (!ObjectUtils.isEmpty(template)) {
                //解析数据
                TemplateRecord templateRecord = null;
                for (Field field : clazz.getDeclaredFields()) {
                    TemplateProp templateProp = field.getAnnotation(TemplateProp.class);
                    if (!ObjectUtils.isEmpty(templateProp)) {
                        templateRecord = BeanCreate.newBean(TemplateRecord.class);
                        templateRecord.setTemplateCode(template.code());
                        templateRecord.setPropertyName(templateProp.name());
                        templateRecord.setProperty(templateProp.property());
                        templateRecord.setBigData(templateProp.bigData());
                        try {
                            PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                            Method get = pd.getReadMethod();
                            Object value = get.invoke(entity);
                            if (!ObjectUtils.isEmpty(value)) {
                                if (templateProp.bigData()) {
                                    templateRecord.setPropertyValue(JSON.toJSONString(value));
                                } else {
                                    templateRecord.setPropertyValue(getValue(value, templateProp));
                                }
                            }
                        } catch (Exception e) {
                            log.info("读取对象属性{}异常", field.getName(), e);
                            throw BusinessExceptionFactory.newException(String.format("读取对象属性%s异常", field.getName()));
                        }
                        list.add(templateRecord);
                    }
                }
            } else {
                log.info("当前类无法读取Template注解，无法解析模板");
            }
        }
        return list;
    }

    /**
     * 生成对象数据
     *
     * @param templateRecords
     * @param tClass
     * @return
     */
    public T readObject(List<TemplateRecord> templateRecords, Class<T> tClass) {
        if (ObjectUtils.isEmpty(templateRecords)) {
            return null;
        }
        try {
            T entity = tClass.newInstance();
            Map<String, String> values = new HashMap<>();
            for (TemplateRecord templateRecord : templateRecords) {
                values.put(templateRecord.getProperty(), templateRecord.getPropertyValue());
            }

            for (Field field : tClass.getDeclaredFields()) {
                TemplateProp templateProp = field.getAnnotation(TemplateProp.class);
                if (!ObjectUtils.isEmpty(templateProp)) {
                    PropertyDescriptor pd = new PropertyDescriptor(field.getName(), tClass);
                    Method set = pd.getWriteMethod();
                    if (templateProp.bigData()) {
                        set.invoke(entity, setBigValue(values.get(templateProp.property()), templateProp));
                    } else {
                        set.invoke(entity, setValue(values.get(templateProp.property()), templateProp));
                    }
                }
            }
            return entity;
        } catch (Exception e) {
            log.info("读取数据异常:{}", e.getMessage(), e);
            throw BusinessExceptionFactory.newException("读取数据异常");
        }
    }

    /**
     * 设置值
     *
     * @param value
     * @param templateProp
     * @return
     */
    private Object setValue(String value, TemplateProp templateProp) throws Exception {
        if (value == null) {
            return null;
        }
        //数据转换
        if (templateProp.dataClass() == Date.class) {
            return new SimpleDateFormat(templateProp.dateFormat()).parse(value);
        } else if (templateProp.dataClass() == Integer.class || templateProp.dataClass() == int.class) {
            return Integer.valueOf(value);
        } else if (templateProp.dataClass() == Double.class || templateProp.dataClass() == double.class) {
            return Double.valueOf(value);
        } else if (templateProp.dataClass() == BigDecimal.class) {
            return new BigDecimal(value);
        } else if (templateProp.dataClass() == Boolean.class || templateProp.dataClass() == boolean.class) {
            return Boolean.valueOf(value);
        } else if (templateProp.dataClass() == Float.class || templateProp.dataClass() == float.class) {
            return Float.valueOf(value);
        } else if (templateProp.dataClass() == Long.class || templateProp.dataClass() == long.class) {
            return Long.valueOf(value);
        } else if (templateProp.dataClass() == Byte.class || templateProp.dataClass() == byte.class) {
            return Byte.valueOf(value);
        } else if (templateProp.dataClass() == Date.class) {
            return new SimpleDateFormat(templateProp.dateFormat()).parse(value);
        } else {
            return String.valueOf(value);
        }
    }

    private Object setBigValue(String value, TemplateProp templateProp) throws Exception {
        return JSON.parseArray(value, templateProp.entityClass());
    }

    /**
     * 获取对象数据
     *
     * @param value
     * @param templateProp
     * @return
     */
    private String getValue(Object value, TemplateProp templateProp) {
        if (ObjectUtils.isEmpty(value)) {
            return null;
        }
        if (templateProp.dataClass() == Date.class) {
            return new SimpleDateFormat(templateProp.dateFormat()).format(value);
        }
        return StringUtil.valueOf(value);
    }


}
